//
//  UIViewController+DragAndPinchScale.m
//  PinchScale
//
//  Created by mac on 2017/4/2.
//  Copyright © 2017年 mac. All rights reserved.
//

#import "UIViewController+DragAndPinchScale.h"

@implementation UIViewController (DragAndPinchScale)

-(NSMutableDictionary *) dictForView:(UIView *)theView{
    NSMutableDictionary *dict = (NSMutableDictionary*) (void*) theView.tag;
    if (!dict) {
        dict = [[NSMutableDictionary dictionary ] retain];
        theView.tag = (NSInteger) (void *) dict;
    }
    
    return dict;
    
}


-(NSMutableDictionary *) dictForViewGuestures:(UIGestureRecognizer *)guesture {
    return [self dictForView:guesture.view];
}


- (IBAction)fingersDidPinchInPinchableView:(UIPinchGestureRecognizer *)fingers {
    NSMutableDictionary *dict = [self dictForViewGuestures:fingers];
    UIView *viewToZoom = fingers.view;
    CGFloat lastScale;
    if([fingers state] == UIGestureRecognizerStateBegan) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = [fingers scale];
    } else {
        lastScale = [[dict objectForKey:@"lastScale"] floatValue];
    }
    
    if ([fingers state] == UIGestureRecognizerStateBegan ||
        [fingers state] == UIGestureRecognizerStateChanged) {
        
        CGFloat currentScale = [[[fingers view].layer valueForKeyPath:@"transform.scale"] floatValue];
        
        // limits to adjust the max/min values of zoom
        CGFloat maxScale = [[dict objectForKey:@"maxScale"] floatValue];
        CGFloat minScale = [[dict objectForKey:@"minScale"] floatValue];
        
        CGFloat newScale = 1 -  (lastScale - [fingers scale]);
        newScale = MIN(newScale, maxScale / currentScale);
        newScale = MAX(newScale, minScale / currentScale);
        CGAffineTransform transform = CGAffineTransformScale([[fingers view] transform], newScale, newScale);
        viewToZoom.transform = transform;
        
        lastScale = [fingers scale];  // Store the previous scale factor for the next pinch gesture call
    }
    
    [dict setObject:[NSNumber numberWithFloat:lastScale]
             forKey:@"lastScale"];
    
}

- (void)fingerDidMoveInDraggableView:(UIPanGestureRecognizer *)finger {
    NSMutableDictionary *dict = [self dictForViewGuestures:finger];
    UIView *viewToDrag =  finger.view;
    if (finger.state == UIGestureRecognizerStateBegan) {
        
        [dict setObject:[NSValue valueWithCGPoint:viewToDrag.frame.origin]
                 forKey:@"startDragOffset"];
        
        [dict setObject:[NSValue valueWithCGPoint:[finger locationInView:self.view]]
                 forKey:@"startDragLocation"];
        
        
    }
    else if (finger.state == UIGestureRecognizerStateChanged) {
        
        NSMutableDictionary *dict = (NSMutableDictionary*) (void*) viewToDrag.tag;
        
        CGPoint stopLocation = [finger locationInView:self.view];
        CGPoint startDragLocation = [[dict valueForKey:@"startDragLocation"] CGPointValue];
        CGPoint startDragOffset = [[dict valueForKey:@"startDragOffset"] CGPointValue];
        CGFloat dx = stopLocation.x - startDragLocation.x;
        CGFloat dy = stopLocation.y - startDragLocation.y;
        //   CGFloat distance = sqrt(dx*dx + dy*dy );
        CGRect dragFrame = viewToDrag.frame;
        
        
        CGSize selfViewSize = self.view.frame.size;
        if (!UIDeviceOrientationIsPortrait(self.interfaceOrientation)) {
            selfViewSize = CGSizeMake(selfViewSize.height,selfViewSize.width);
        }
        
        selfViewSize.width  -= dragFrame.size.width;
        selfViewSize.height -= dragFrame.size.height;
        
        dragFrame.origin.x = MIN(selfViewSize.width, MAX(0,startDragOffset.x+dx));
        dragFrame.origin.y = MIN(selfViewSize.height,MAX(0,startDragOffset.y+dy));
        
        viewToDrag.frame = dragFrame;
    }
    else if (finger.state == UIGestureRecognizerStateEnded) {
        
        [dict removeObjectForKey:@"startDragLocation"];
        [dict removeObjectForKey:@"startDragOffset"];
    }
}

-(void) makeView:(UIView*)aView
       draggable:(BOOL)draggable
       pinchable:(BOOL)pinchable
   minPinchScale:(CGFloat)minPinchScale
   maxPinchScale:(CGFloat)maxPinchScale{
    NSMutableDictionary *dict = (NSMutableDictionary*) (void*) aView.tag;
    
    if (!(pinchable || draggable)) {
        
        if (dict){
            [dict release];
            aView.tag = 0;
        }
        return;
    }
    
    if (dict) {
        
        UIPanGestureRecognizer *pan =[dict objectForKey:@"UIPanGestureRecognizer"];
        if(pan){
            if ([aView.gestureRecognizers indexOfObject:pan]!=NSNotFound) {
                [aView removeGestureRecognizer:pan];
            }
            [dict removeObjectForKey:@"UIPanGestureRecognizer"];
        }
        
        UIPinchGestureRecognizer *pinch =[dict objectForKey:@"UIPinchGestureRecognizer"];
        if(pinch){
            if ([aView.gestureRecognizers indexOfObject:pinch]!=NSNotFound) {
                [aView removeGestureRecognizer:pinch];
            }
            [dict removeObjectForKey:@"UIPinchGestureRecognizer"];
        }
        
        [dict removeObjectForKey:@"startDragLocation"];
        [dict removeObjectForKey:@"startDragOffset"];
        [dict removeObjectForKey:@"lastScale"];
        [dict removeObjectForKey:@"minScale"];
        [dict removeObjectForKey:@"maxScale"];
    }
    
    
    if (draggable) {
        
        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(fingerDidMoveInDraggableView:)];
        pan.minimumNumberOfTouches = 1;
        pan.maximumNumberOfTouches = 1;
        [aView addGestureRecognizer:pan];
        [pan release];
        
        dict = [self dictForViewGuestures:pan];
        [dict setObject:pan forKey:@"UIPanGestureRecognizer"];
        
    }
    
    if (pinchable) {
        
        
        CGAffineTransform initialTramsform = CGAffineTransformMakeScale(1.0, 1.0);
        aView.transform = initialTramsform;
        
        
        UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(fingersDidPinchInPinchableView:)];
        [aView addGestureRecognizer:pinch];
        [pinch release];
        dict = [self dictForViewGuestures:pinch];
        [dict setObject:pinch forKey:@"UIPinchGestureRecognizer"];
        [dict setObject:[NSNumber numberWithFloat:minPinchScale] forKey:@"minScale"];
        [dict setObject:[NSNumber numberWithFloat:maxPinchScale] forKey:@"maxScale"];
        
        
    }
}
@end
